/**
 * uifuture.com
 * Copyright (C) 2013-2018 All Rights Reserved.
 */
package com.netty.client;

import com.netty.config.ChannelContainer;
import com.netty.message.MessageProtocol;
import com.netty.protobuf.MessageProto;
import com.netty.util.SpringUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @author
 */
@Component
@ChannelHandler.Sharable
public class ClientChannelHandler extends ChannelInboundHandlerAdapter {


    /**
     * 通道注册
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
    }

    /**
     * 服务器的连接被建立后调用
     * 建立连接后该 channelActive() 方法被调用一次
     *
     * @param ctx
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        System.out.println("建立连接时："+new Date());
        ChannelContainer channelContainer = SpringUtil.getBean(ChannelContainer.class);
        channelContainer.setChannel(ctx.channel());
    }

    /**
     * 关闭连接时
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //使用过程中断线重连
        System.out.println("使用过程中服务端链接不上，开始重连操作...");
        Thread.sleep(1000);
        new NettyClient().start();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {
        if (obj instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) obj;
            //如果写通道处于空闲状态,就发送心跳命令
            //实体类发送心跳数据
            if (IdleState.WRITER_IDLE.equals(event.state())) {
                String socketString = ctx.channel().localAddress().toString();
                ctx.channel().writeAndFlush("hello");
                MessageProto.Message ping = MessageProto.Message.newBuilder().setId(socketString).setContent("hello").build();
                ctx.channel().writeAndFlush(ping);
            }

            //自定义协议发送心跳数据
//            if(IdleState.WRITER_IDLE.equals(event.state())){
//                // 获得要发送信息的字节数组
//                String data = "hello";
//                byte[] content = data.getBytes();
//                // 要发送信息的长度
//                int contentLength = content.length;
//                MessageProtocol protocol = new MessageProtocol(contentLength, content);
//                ctx.channel().writeAndFlush(protocol);
//            }
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        //实体类读取接收的数据
        MessageProto.Message message = (MessageProto.Message) msg;
        String socketString = ctx.channel().remoteAddress().toString();
        System.out.println("server:"+socketString+":"+message.getContent());

        ctx.fireChannelRead(msg);


        //自定义协议接收数据
//        try {
//            // 用于获取客户端发来的数据信息
//            MessageProtocol body = (MessageProtocol) msg;
//            System.out.println("server :" + new String(body.getContent()));
//        } finally {
//            ReferenceCountUtil.release(msg);
//        }
    }

    /**
     * 捕获异常时调用
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
                                Throwable cause)  throws Exception{
        //记录错误日志并关闭 channel
        super.exceptionCaught(ctx, cause);
        cause.printStackTrace();
        Channel channel = ctx.channel();
        if(channel.isActive()){
            ctx.close();
        }
    }

}
